package com.xjrsoft.common.utils;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.Enum.TransDataType;
import com.xjrsoft.common.annotation.DataTrans;
import com.xjrsoft.common.result.Response;
import com.xjrsoft.core.tool.utils.*;
import com.xjrsoft.module.base.entity.*;
import com.xjrsoft.module.base.service.IXjrBaseAnnexesFileService;
import com.xjrsoft.module.base.service.IXjrBaseAreaService;
import com.xjrsoft.module.base.service.IXjrBaseDataItemService;
import com.xjrsoft.module.base.service.IXjrBaseDatasourceService;
import com.xjrsoft.module.base.utils.OrganizationCacheUtil;
import com.xjrsoft.module.base.vo.DataItemDetailVo;
import com.xjrsoft.module.interfaceManager.service.IXjrInterfaceInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class DataTransUtil {

    private static final IXjrBaseDataItemService dataItemService;

    private static final IXjrBaseDatasourceService datasourceService;

    private static final IXjrBaseAnnexesFileService annexesFileService;

    private static final IXjrBaseAreaService areaService;

    private static final IXjrInterfaceInfoService interfaceInfoService;

    static{
        dataItemService = SpringUtil.getBean(IXjrBaseDataItemService.class);
        datasourceService = SpringUtil.getBean(IXjrBaseDatasourceService.class);
        annexesFileService = SpringUtil.getBean(IXjrBaseAnnexesFileService.class);
        areaService = SpringUtil.getBean(IXjrBaseAreaService.class);
        interfaceInfoService = SpringUtil.getBean(IXjrInterfaceInfoService.class);
    }

    private DataTransUtil(){}

    /**
     * 转换列表显示的值
     * @param transList
     * @param <T>
     */
    public static <T> void transListShowData(List<T> transList) {
        // 数据准备
        Map<String, Map<String, Object>> dataMap = new HashMap<>(16);
        Map<String, String> multiValueSeparatorMap = new HashMap<>(16);
        if (CollectionUtil.isNotEmpty(transList)) {
            Map<String, DataTrans> fieldDataTransAnnotationMap = new HashMap<>(8);
            Map<String, List<Object>> transValueMap = new HashMap<>(fieldDataTransAnnotationMap.size());
            Class<?> clazz = transList.get(0).getClass();
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                DataTrans annotation = field.getAnnotation(DataTrans.class);
                if (annotation == null) {
                    continue;
                }
                String name = field.getName();
                fieldDataTransAnnotationMap.put(name, annotation);
                for (T data : transList) {
                    Object property = BeanUtil.getProperty(data, name);
                    if (!StringUtil.isEmpty(property)) {
                        List<Object> values = transValueMap.get(name);
                        if (CollectionUtil.isEmpty(values)) {
                            values = new ArrayList<>();
                            transValueMap.put(name, values);
                        }
                        if (annotation.multi()) {
                            values.addAll(Arrays.asList(StringUtils.split(String.valueOf(property), StringPool.COMMA)));
                        } else if (annotation.dataType() == TransDataType.CASCADE) {
                            values.add(StringUtils.substringAfterLast(String.valueOf(property), StringPool.COMMA));
                        }else {
                            values.add(property);
                        }
                    }
                }
            }
            // 查询转换的数据
            for (Map.Entry<String, DataTrans> entry : fieldDataTransAnnotationMap.entrySet()) {
                DataTrans annotation = entry.getValue();
                String fieldName = entry.getKey();
                List<Object> values = transValueMap.get(fieldName);
                if (CollectionUtil.isEmpty(values)) {
                    continue;
                }
                Map<String, Object> data = new HashMap<>(16);
                TransDataType transDataType = annotation.dataType();
                switch (transDataType) {
                    case DATA_ITEM:
                        // 数据字典
                        String itemCode = annotation.dataCode();
                        List<DataItemDetailVo> dataItemDetails = dataItemService.getDataItemDetails(itemCode);
                        for (DataItemDetailVo detail: dataItemDetails) {
                            data.put(detail.getItemValue(), detail.getItemName());
                        }
                        break;
                    case DATA_SOURCE:
                        // 数据源
                        String datasourceId = annotation.dataCode();
                        String showField = annotation.showField();
                        String saveField = annotation.savedField();
                        String columns = showField + StringPool.COMMA + saveField;
                        try {
                            List<Map<String, Object>> datasourceDataList = datasourceService.getDataByColumns(datasourceId, columns);
                            for (Map<String, Object> resultData : datasourceDataList) {
                                data.put(String.valueOf(resultData.get(saveField)), resultData.get(showField));
                            }
                        } catch (Exception e) {
                            log.error("查询数据源失败！id: " + datasourceId, e);
                        }
                        break;
                    case DATA_SQL:
                        // 数据源
                        String dbId = annotation.dataCode();
                        String sqlShowField = annotation.showField();
                        String sqlSaveField = annotation.savedField();
                        String sql = annotation.sql();
                        String sqlColumns = sqlShowField + StringPool.COMMA + sqlSaveField;
                        List<Map<String, Object>> datasourceDataList = datasourceService.getDataBySql(dbId, sql, sqlColumns);
                        for (Map<String, Object> resultData : datasourceDataList) {
                            data.put(String.valueOf(resultData.get(sqlSaveField)), resultData.get(sqlShowField));
                        }
                        break;
                    case API :
                        String id = annotation.dataCode();
                        String prefix = annotation.sql();
                        String apiShowField = annotation.showField();
                        String apiSaveField = annotation.savedField();
                        Object resultData = null;
                        try {
                            Response response = interfaceInfoService.execute(id, new HashMap<>(), WebUtil.getRequest());
                            resultData = (Map) response.getData();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                        if (resultData == null) {
                            break;
                        }
                        List<Map<String, Object>> jsonArray = (List<Map<String, Object>>)(StringUtil.isEmpty(prefix) ? resultData : ((Map<String, Object>)resultData).get(prefix));
                        for (Map<String, Object> item: jsonArray) {
                            data.put(MapUtils.getString(item, apiSaveField), MapUtils.getString(item, apiShowField));
                        }
                        break;
                    case COMPANY:
                        // 公司
                        List<XjrBaseCompany> companyList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.COMPANY_LIST_CACHE_KEY, values);
                        for (XjrBaseCompany company : companyList) {
                            data.put(company.getCompanyId(), company.getFullName());
                        }
                        break;
                    case DEPARTMENT:
                        // 部门
                        List<XjrBaseDepartment> allDepartmentList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.DEPARTMENT_LIST_CACHE_KEY, values);
                        for (XjrBaseDepartment department : allDepartmentList) {
                            data.put(department.getDepartmentId(), department.getFullName());
                        }
                        break;
                    case USER:
                        // 人员
                        List<XjrBaseUser> allUserList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.USER_LIST_CACHE_KEY, values);
                        for (XjrBaseUser user : allUserList) {
                            data.put(user.getUserId(), user.getRealName());
                        }
                    case AREA:
                        List<XjrBaseArea> areaList = areaService.list(Wrappers.<XjrBaseArea>query().lambda().in(XjrBaseArea::getAreaCode, values));
                        for (XjrBaseArea area : areaList ) {
                            data.put(area.getAreaCode(), area.getAreaName());
                        }
                        break;
                    case CASCADE:
                        String[] dataSourceIds = annotation.dataCodes();
                        String[] showFields = annotation.showFields();
                        String[] saveFields = annotation.savedFields();
                        boolean multi = annotation.multi();
                        int start = multi ? 0 : showFields.length - 1;
                        for (int i = start; i < showFields.length; i++) {
                            List<Map<String, Object>> dataList = null;
                            try {
                                dataList = datasourceService.getDataList(dataSourceIds[i], null, null, null, null);
                            } catch (Exception e) {
                                log.error("数据转换，查询sql数据失败！", e);
                            }
                            if (CollectionUtil.isNotEmpty(dataList)) {
                                for (Map<String, Object> map : dataList) {
                                    data.put(String.valueOf(map.get(saveFields[i])), map.get(showFields[i]));
                                }
                            }
                        }
                        break;
//                    case CH_YUAN:
//                        if (CollectionUtil.isNotEmpty(values)) {
//                            for (Object obj : values) {
//                                String amount = String.valueOf(obj);
//                                data.put(amount, ChineseYuanUtil.convertToYuan(amount));
//                            }
//                        }
//                        break;
                    case PASSWORD:
                        if (CollectionUtil.isNotEmpty(values)) {
                            for (Object obj : values) {
                                String amount = String.valueOf(obj);
                                data.put(amount, "******");
                            }
                        }
                        break;
                    case FILE:
                        List<XjrBaseAnnexesFile> annexesFileList = annexesFileService.list(Wrappers.<XjrBaseAnnexesFile>query()
                                .lambda().in(XjrBaseAnnexesFile::getFolderId, values));
                        if (CollectionUtil.isNotEmpty(annexesFileList)) {
                            for (XjrBaseAnnexesFile annexesFile : annexesFileList) {
                                String folderId = annexesFile.getFolderId();
                                String fileName = annexesFile.getFileName();
                                StringBuilder stringBuilder = (StringBuilder) data.get(folderId);
                                if (stringBuilder == null) {
                                    stringBuilder = new StringBuilder(fileName);
                                    data.put(folderId, stringBuilder);
                                } else {
                                    stringBuilder.append(", " + fileName);
                                }
                            }
                        }
                }
                if (annotation.multi()) {
                    // 多选字段
                    multiValueSeparatorMap.put(fieldName, annotation.separator());
                }
                dataMap.put(fieldName, data);
            }

            // 填充转换数据
            for (T record : transList) {
                for (String fieldName : dataMap.keySet()) {
                    Object value = BeanUtil.getProperty(record, fieldName);
                    Map<String, Object> data = dataMap.get(fieldName);
                    if (data == null || value == null) {
                        continue;
                    }
                    Object transToValue = null;
                    if (multiValueSeparatorMap.keySet().contains(fieldName) && !StringUtil.isEmpty(value)) {
                        StringBuilder sb = new StringBuilder();
                        String[] values = StringUtils.split(String.valueOf(value), StringPool.COMMA);
                        for (String s : values) {
                            Object v = data.get(s);
                            if (StringUtil.isEmpty(v)) {
                                continue;
                            }
                            if (sb.length() > 0) {
                                sb.append(multiValueSeparatorMap.get(fieldName));
                            }
                            sb.append(v);
                        }
                        transToValue = sb.toString();
                    } else {
                        transToValue = data.get(String.valueOf(value));
                    }
                    if (transToValue != null && !"".equals(transToValue)) {
                        if (transToValue instanceof LocalDateTime) {
                            transToValue = ((LocalDateTime) transToValue).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        } else if(transToValue instanceof Date) {
                            transToValue = DateUtil.formatDateTime((Date)transToValue);
                        } else {
                            transToValue = String.valueOf(transToValue);
                        }
                        BeanUtil.setProperty(record, fieldName, transToValue);
                    }
                }
            }
        }
    }

    public static String getCompanyNameById(String companyId){
        List<XjrBaseCompany> companyList = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.COMPANY_LIST_CACHE_KEY);
        for (XjrBaseCompany company : companyList) {
            if (StringUtil.equals(companyId, company.getCompanyId())) {
                return company.getFullName();
            }
        }
        return null;
    }

    public static String getDepartmentNameById(String departmentId){
        List<XjrBaseDepartment> departmentList = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.DEPARTMENT_LIST_CACHE_KEY);
        for (XjrBaseDepartment department : departmentList) {
            if (StringUtil.equals(departmentId, department.getDepartmentId())) {
                return department.getFullName();
            }
        }
        return null;
    }
}
